home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_kernel_source / LIB / VSPRINTF.C < prev   
C/C++ Source or Header  |  1999-09-17  |  6KB  |  319 lines

  1. /*
  2.  *  linux/lib/vsprintf.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  8. /*
  9.  * Wirzenius wrote this portably, Torvalds fucked it up :-)
  10.  */
  11.  
  12. #include <stdarg.h>
  13. #include <linux/types.h>
  14. #include <linux/string.h>
  15. #include <linux/ctype.h>
  16.  
  17. unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  18. {
  19.     unsigned long result = 0,value;
  20.  
  21.     if (!base) {
  22.         base = 10;
  23.         if (*cp == '0') {
  24.             base = 8;
  25.             cp++;
  26.             if ((*cp == 'x') && isxdigit(cp[1])) {
  27.                 cp++;
  28.                 base = 16;
  29.             }
  30.         }
  31.     }
  32.     while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  33.         ? toupper(*cp) : *cp)-'A'+10) < base) {
  34.         result = result*base + value;
  35.         cp++;
  36.     }
  37.     if (endp)
  38.         *endp = (char *)cp;
  39.     return result;
  40. }
  41.  
  42. long simple_strtol(const char *cp,char **endp,unsigned int base)
  43. {
  44.     if(*cp=='-')
  45.         return -simple_strtoul(cp+1,endp,base);
  46.     return simple_strtoul(cp,endp,base);
  47. }
  48.  
  49. /* we use this so that we can do without the ctype library */
  50. #define is_digit(c)    ((c) >= '0' && (c) <= '9')
  51.  
  52. static int skip_atoi(const char **s)
  53. {
  54.     int i=0;
  55.  
  56.     while (is_digit(**s))
  57.         i = i*10 + *((*s)++) - '0';
  58.     return i;
  59. }
  60.  
  61. #define ZEROPAD    1        /* pad with zero */
  62. #define SIGN    2        /* unsigned/signed long */
  63. #define PLUS    4        /* show plus */
  64. #define SPACE    8        /* space if plus */
  65. #define LEFT    16        /* left justified */
  66. #define SPECIAL    32        /* 0x */
  67. #define LARGE    64        /* use 'ABCDEF' instead of 'abcdef' */
  68.  
  69. #define do_div(n,base) ({ \
  70. int __res; \
  71. __res = ((unsigned long) n) % (unsigned) base; \
  72. n = ((unsigned long) n) / (unsigned) base; \
  73. __res; })
  74.  
  75. static char * number(char * str, long num, int base, int size, int precision
  76.     ,int type)
  77. {
  78.     char c,sign,tmp[66];
  79.     const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  80.     int i;
  81.  
  82.     if (type & LARGE)
  83.         digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  84.     if (type & LEFT)
  85.         type &= ~ZEROPAD;
  86.     if (base < 2 || base > 36)
  87.         return 0;
  88.     c = (type & ZEROPAD) ? '0' : ' ';
  89.     sign = 0;
  90.     if (type & SIGN) {
  91.         if (num < 0) {
  92.             sign = '-';
  93.             num = -num;
  94.             size--;
  95.         } else if (type & PLUS) {
  96.             sign = '+';
  97.             size--;
  98.         } else if (type & SPACE) {
  99.             sign = ' ';
  100.             size--;
  101.         }
  102.     }
  103.     if (type & SPECIAL) {
  104.         if (base == 16)
  105.             size -= 2;
  106.         else if (base == 8)
  107.             size--;
  108.     }
  109.     i = 0;
  110.     if (num == 0)
  111.         tmp[i++]='0';
  112.     else while (num != 0)
  113.         tmp[i++] = digits[do_div(num,base)];
  114.     if (i > precision)
  115.         precision = i;
  116.     size -= precision;
  117.     if (!(type&(ZEROPAD+LEFT)))
  118.         while(size-->0)
  119.             *str++ = ' ';
  120.     if (sign)
  121.         *str++ = sign;
  122.     if (type & SPECIAL) {
  123.         if (base==8)
  124.             *str++ = '0';
  125.         else if (base==16) {
  126.             *str++ = '0';
  127.             *str++ = digits[33];
  128.         }
  129.     }
  130.     if (!(type & LEFT))
  131.         while (size-- > 0)
  132.             *str++ = c;
  133.     while (i < precision--)
  134.         *str++ = '0';
  135.     while (i-- > 0)
  136.         *str++ = tmp[i];
  137.     while (size-- > 0)
  138.         *str++ = ' ';
  139.     return str;
  140. }
  141.  
  142. /* Forward decl. needed for IP address printing stuff... */
  143. int sprintf(char * buf, const char *fmt, ...);
  144.  
  145. int vsprintf(char *buf, const char *fmt, va_list args)
  146. {
  147.     int len;
  148.     unsigned long num;
  149.     int i, base;
  150.     char * str;
  151.     const char *s;
  152.  
  153.     int flags;        /* flags to number() */
  154.  
  155.     int field_width;    /* width of output field */
  156.     int precision;        /* min. # of digits for integers; max
  157.                    number of chars for from string */
  158.     int qualifier;        /* 'h', 'l', or 'L' for integer fields */
  159.  
  160.     for (str=buf ; *fmt ; ++fmt) {
  161.         if (*fmt != '%') {
  162.             *str++ = *fmt;
  163.             continue;
  164.         }
  165.             
  166.         /* process flags */
  167.         flags = 0;
  168.         repeat:
  169.             ++fmt;        /* this also skips first '%' */
  170.             switch (*fmt) {
  171.                 case '-': flags |= LEFT; goto repeat;
  172.                 case '+': flags |= PLUS; goto repeat;
  173.                 case ' ': flags |= SPACE; goto repeat;
  174.                 case '#': flags |= SPECIAL; goto repeat;
  175.                 case '0': flags |= ZEROPAD; goto repeat;
  176.                 }
  177.         
  178.         /* get field width */
  179.         field_width = -1;
  180.         if (is_digit(*fmt))
  181.             field_width = skip_atoi(&fmt);
  182.         else if (*fmt == '*') {
  183.             ++fmt;
  184.             /* it's the next argument */
  185.             field_width = va_arg(args, int);
  186.             if (field_width < 0) {
  187.                 field_width = -field_width;
  188.                 flags |= LEFT;
  189.             }
  190.         }
  191.  
  192.         /* get the precision */
  193.         precision = -1;
  194.         if (*fmt == '.') {
  195.             ++fmt;    
  196.             if (is_digit(*fmt))
  197.                 precision = skip_atoi(&fmt);
  198.             else if (*fmt == '*') {
  199.                 ++fmt;
  200.                 /* it's the next argument */
  201.                 precision = va_arg(args, int);
  202.             }
  203.             if (precision < 0)
  204.                 precision = 0;
  205.         }
  206.  
  207.         /* get the conversion qualifier */
  208.         qualifier = -1;
  209.         if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  210.             qualifier = *fmt;
  211.             ++fmt;
  212.         }
  213.  
  214.         /* default base */
  215.         base = 10;
  216.  
  217.         switch (*fmt) {
  218.         case 'c':
  219.             if (!(flags & LEFT))
  220.                 while (--field_width > 0)
  221.                     *str++ = ' ';
  222.             *str++ = (unsigned char) va_arg(args, int);
  223.             while (--field_width > 0)
  224.                 *str++ = ' ';
  225.             continue;
  226.  
  227.         case 's':
  228.             s = va_arg(args, char *);
  229.             if (!s)
  230.                 s = "<NULL>";
  231.  
  232.             len = strnlen(s, precision);
  233.  
  234.             if (!(flags & LEFT))
  235.                 while (len < field_width--)
  236.                     *str++ = ' ';
  237.             for (i = 0; i < len; ++i)
  238.                 *str++ = *s++;
  239.             while (len < field_width--)
  240.                 *str++ = ' ';
  241.             continue;
  242.  
  243.         case 'p':
  244.             if (field_width == -1) {
  245.                 field_width = 2*sizeof(void *);
  246.                 flags |= ZEROPAD;
  247.             }
  248.             str = number(str,
  249.                 (unsigned long) va_arg(args, void *), 16,
  250.                 field_width, precision, flags);
  251.             continue;
  252.  
  253.  
  254.         case 'n':
  255.             if (qualifier == 'l') {
  256.                 long * ip = va_arg(args, long *);
  257.                 *ip = (str - buf);
  258.             } else {
  259.                 int * ip = va_arg(args, int *);
  260.                 *ip = (str - buf);
  261.             }
  262.             continue;
  263.  
  264.         case '%':
  265.             *str++ = '%';
  266.             continue;
  267.  
  268.         /* integer number formats - set up the flags and "break" */
  269.         case 'o':
  270.             base = 8;
  271.             break;
  272.  
  273.         case 'X':
  274.             flags |= LARGE;
  275.         case 'x':
  276.             base = 16;
  277.             break;
  278.  
  279.         case 'd':
  280.         case 'i':
  281.             flags |= SIGN;
  282.         case 'u':
  283.             break;
  284.  
  285.         default:
  286.             *str++ = '%';
  287.             if (*fmt)
  288.                 *str++ = *fmt;
  289.             else
  290.                 --fmt;
  291.             continue;
  292.         }
  293.         if (qualifier == 'l')
  294.             num = va_arg(args, unsigned long);
  295.         else if (qualifier == 'h') {
  296.             num = (unsigned short) va_arg(args, int);
  297.             if (flags & SIGN)
  298.                 num = (short) num;
  299.         } else if (flags & SIGN)
  300.             num = va_arg(args, int);
  301.         else
  302.             num = va_arg(args, unsigned int);
  303.         str = number(str, num, base, field_width, precision, flags);
  304.     }
  305.     *str = '\0';
  306.     return str-buf;
  307. }
  308.  
  309. int sprintf(char * buf, const char *fmt, ...)
  310. {
  311.     va_list args;
  312.     int i;
  313.  
  314.     va_start(args, fmt);
  315.     i=vsprintf(buf,fmt,args);
  316.     va_end(args);
  317.     return i;
  318. }
  319.